-- chain_damage
-- create by panyl
-- 技能：链式伤害，对周围怪物造成伤害，伤害依次减半，最少1点
-- 目前支持如下配置：
-- chain_damage(1200,radius)：对目标造成 1200威力 * 魔力 的魔法伤害

return {
    apply = function(source, target, skillId, round, para, extra)
        local force = para[1];
        local radius = para[2];

        if radius < 0 then
            radius = MAX_VALUE;
        end

        local addon_rate = 0;

        local combine = PropM.combine;
        local PropM_apply = PropM.apply;
        local fetchProps = PropM.fetchProps;
        local trigger = PropM.trigger;

        -- 计算魔法效果加成
        local addon_rate = SkillM.calcMagicEffectAddon(source, skillId, true);

        --最终威力
        local force = math.modf(force * (addon_rate + 1000)/1000);

        -- 2. 攻击方的魔力
        local magic = source:getMagic();

        -- 被对方百分比削弱
        local prop = combine(target, "weak_enemy", "magic");
        magic = PropM_apply(prop, magic);

        -- 被对方绝对值削弱
        prop = combine(target, "weak_enemy2", "magic");
        magic = PropM_apply(prop, magic);

        -- 3. 伤害
        local damage = math.modf(force * (magic + 3)/ 1000);

        -- 魔法暴击类，多种暴击线性叠加伤害
        local addon_damage = 0;

        -- 伤害类魔法概率增强
        local props = fetchProps(source, "damage_magic");
        for _, prop in ipairs(props) do
            addon_damage = addon_damage + trigger(source, prop[1], prop[2], damage);
        end
        -- 魔法暴击
        props = fetchProps(source, "critical_magic");
        for _, prop in ipairs(props) do
            addon_damage = addon_damage + trigger(source, prop[1], prop[2], damage);
        end
        -- 概率双倍
        props = fetchProps(source, "skill_double");
        for _, prop in ipairs(props) do
            if tonumber(prop[2]) == skillId then
                addon_damage = addon_damage + trigger(source, prop[1], prop[2], damage);
            end
        end
        -- 最终伤害
        damage = damage + addon_damage;

        -- 魔法抗性
        prop = combine(target, "resist", "magic");
        -- 忽视抗性
        local p = combine(source, "ignore_resist", skillId);
        prop[3] = PropM_apply(p, prop[3]);
        p = combine(source, "ignore_resist", "magic");
        prop[3] = PropM_apply(p, prop[3]);

        damage = PropM_apply(prop, damage);

        -- 增加命中动作
        SkillM.getSequence(target):hit(source, target, skillId);

        -- 天赋影响伤害削减
        local cut = 500;
        prop = combine(source, "elect_sputtering", skillId);
        cut = PropM_apply(prop, cut);

        -- 先给目标受创，然后伤害减半
        CombatM.receiveDamage(source, target, damage, skillId, extra);
        damage = math.modf(damage * (1000 - cut) / 1000);
        damage = math.max(1, damage);

        -- 如果第一目标免疫了，不再链接
        if SkillM.immunitySkill(source, target, skillId) then
            return damage;
        end

        -- 4. 遍历怪物周围所有已开且存活且不魔免的怪
        local pos = target.dbase:query("pos");
        if not pos then
            pos = target:getOwner();
        end

        local from = target;

        local coor = DungeonM.convertToCoor(pos);
        local ret = {};

        local linkCount = 1;
        for index = 1, GRID_SIZE do
            repeat
                local c = DungeonM.convertToCoor(index);

                if math.abs(coor.x - c.x) > radius or math.abs(coor.y - c.y) > radius then
                    break;
                end

                local grid = DungeonM.getGridByPos(index);

                -- 已开启且未死亡的怪物且不是原目标，且不免疫该技能
                if  grid:isOpened() and grid:isMonster() and
                    not grid.monster:isDead() and
                    grid.monster ~= target and
                    not SkillM.immunitySkill(source, grid.monster, skillId) then
                    -- 增加命中动作
                    if SkillM.getSequence(grid.monster) == nil then
                        SkillM.getSequenceList()[grid.monster] = CastSequence.create(source, grid.monster, skillId);
                    end

                    -- 延迟，等上一个命中结束
                    SkillM.getSequence(grid.monster):delay(source, grid.monster, 0.1 * linkCount);

                    -- 链接效果
                    SkillM.getSequence(grid.monster):link(from, grid.monster, skillId, linkCount);
                    from = grid.monster;
                    linkCount = linkCount + 1;

                    -- 命中
                    SkillM.getSequence(grid.monster):hit(source, grid.monster, skillId);

                    -- 魔法抗性
                    prop = combine(grid.monster, "resist", "magic");
                    -- 忽视抗性
                    local p = combine(source, "ignore_resist", skillId);
                    prop[3] = PropM_apply(p, prop[3]);
                    p = combine(source, "ignore_resist", "magic");
                    prop[3] = PropM_apply(p, prop[3]);

                    local finalDamage = PropM_apply(prop, damage);

                    CombatM.receiveDamage(source, grid.monster, finalDamage, skillId, extra);

                    damage = math.modf(damage * (1000 - cut) / 1000);
                    damage = math.max(1, damage);

                    -- 目标
                    table.insert(ret, grid.monster);
                end
            until true;
        end

        -- 作用目标
        return ret;
    end,

    parse = function(desc)
        local arr = string.explode(desc, ",");
        return { tonumber(arr[1]), tonumber(arr[2] or -1), };
    end,

    -- 解析技能描述
    parseDesc = function(source, skillId, desc, para)
        local base = para[1];

        -- 计算魔法效果加成
        local addon_rate = SkillM.calcMagicEffectAddon(source, skillId, false);

        --最终威力
        local force = math.modf(base * (addon_rate + 1000)/1000);

        -- 2. 攻击方的魔力
        local magic = source:getMagic();

        -- 3. 伤害
        local damageBase = math.modf(base * (magic + 3) / 1000);
        local damageForce = math.modf(force * (magic + 3) / 1000);
        local damageAddon = damageForce - damageBase;
        if damageAddon == 0 then
            desc = string.gsub(desc, "{chain_damage}", damageForce);
        else
            desc = string.gsub(desc, "{chain_damage}", damageBase .. "(+" .. damageAddon .. ")");
        end

        -- 4. 溅射削减比例
        local cut = 500;
        local prop = PropM.combine(source, "elect_sputtering", skillId);
        cut = PropM.apply(prop, cut);

        desc = string.gsub(desc, "{cut}", cut / 10);

        -- 系别TODO
        return desc;
    end,
};
